package com.molichuxing.services.infrastructure.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.result.ResponseCodeEnum;
import com.molichuxing.framework.utils.MapObjectConvertUtil;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.framework.utils.StringUtil;
import com.molichuxing.services.infrastructure.dto.request.create.IovFenceBindingCreateDto;
import com.molichuxing.services.infrastructure.dto.request.create.IovFenceCreateDto;
import com.molichuxing.services.infrastructure.dto.request.modify.IovFenceBindingModifyDto;
import com.molichuxing.services.infrastructure.dto.request.modify.IovFenceModifyDto;
import com.molichuxing.services.infrastructure.dto.response.IovFenceDto;
import com.molichuxing.services.infrastructure.dto.response.IovResponseDto;
import com.molichuxing.services.infrastructure.service.IovFenceService;
import com.molichuxing.services.property.IovFenceAlarmTypeEnum;
import com.molichuxing.services.util.IovPropertyUtils;
import com.molichuxing.services.util.IovUtils;

/**
 * @author zhaopenghui
 * 车联网围栏服务
 * 2019-10-29
 */
@Service("iovFenceService")
public class IovFenceServiceImpl implements IovFenceService {
    private static final Logger logger = LoggerFactory.getLogger(IovFenceServiceImpl.class);

    @Resource
    private IovUtils iovUtils;

    /**
     * 添加围栏
     *
     * @param iovFenceCreateDto
     * @return
     * @throws Exception
     */
    @Override
    public Integer addFence(IovFenceCreateDto iovFenceCreateDto) throws Exception {
        if (null == iovFenceCreateDto) {
            logger.error("[addFence]调用车联网，添加围栏，入参为空");
            throw new BizException("添加围栏失败");
        }

        Map<String, Object> paramMap = MapObjectConvertUtil.objectToMap(iovFenceCreateDto);
        if (null == paramMap || paramMap.size() < 1) {
            logger.error("[addFence]调用车联网，添加围栏，入参转map失败");
            throw new BizException("添加围栏失败");
        }

        IovResponseDto iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_ADD, paramMap);
        logger.info("[addFence]添加围栏调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
        if (!iovResponse.getFlag()) {
            throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
        }
        String data = iovResponse.getData();
        JSONObject jsonObject = JSONObject.parseObject(data);
        Long fenceId = ObjectCastUtil.castLongPackType(jsonObject.get("id"));
        if (null == fenceId) {
            return null;
        }
        return fenceId.intValue();
    }

    /**
     * 修改围栏
     *
     * @param iovFenceModifyDto
     * @return
     * @throws Exception
     */
    @Override
    public Boolean modifyFence(IovFenceModifyDto iovFenceModifyDto) throws Exception {
        if (null == iovFenceModifyDto) {
            logger.error("[modifyFence]调用车联网，修改围栏，入参为空");
            throw new BizException("修改围栏失败");
        }

        Map<String, Object> paramMap = MapObjectConvertUtil.objectToMap(iovFenceModifyDto);
        if (null == paramMap || paramMap.size() < 1) {
            logger.error("[modifyFence]调用车联网，修改围栏，入参转map失败");
            throw new BizException("修改围栏失败");
        }

        IovResponseDto iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_MODIFY, paramMap);
        logger.info("[modifyFence]修改围栏调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
        if (!iovResponse.getFlag()) {
            throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
        }

        return true;
    }

    /**
     * 删除围栏
     *
     * @param fenceId
     * @return
     * @throws Exception
     */
    @Override
    public Boolean deleteFence(Integer fenceId) throws Exception {
        if (null == fenceId) {
            logger.error("[deleteFence]调用车联网，删除围栏，入参为空");
            throw new BizException("删除围栏失败");
        }

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("id", fenceId);
        IovResponseDto iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_DELETE, paramMap);
        logger.info("[deleteFence]删除围栏调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
        if (!iovResponse.getFlag()) {
            throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
        }

        return true;
    }

    /**
     * 围栏绑定
     *
     * @param iovFenceBindingCreateDto
     * @return
     * @throws Exception
     */
    @Override
    public Boolean addBindingFence(IovFenceBindingCreateDto iovFenceBindingCreateDto) throws Exception {
        if (null == iovFenceBindingCreateDto) {
            logger.error("[addBindingFence]调用车联网，绑定围栏，入参为空");
            throw new BizException("绑定围栏失败");
        }

        Map<String, Object> paramMap = MapObjectConvertUtil.objectToMap(iovFenceBindingCreateDto);
        if (null == paramMap || paramMap.size() < 1) {
            logger.error("[addBindingFence]调用车联网，绑定围栏，入参转map失败");
            throw new BizException("绑定围栏失败");
        }

        IovResponseDto iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_BINDING, paramMap);
        logger.info("[addBindingFence]围栏绑定调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
        if (!iovResponse.getFlag()) {
            throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
        }

        return true;
    }

    /**
     * 解绑围栏
     *
     * @param iovFenceBindingModifyDto
     * @return
     * @throws Exception
     */
    @Override
    public Boolean modifyBindingFence(IovFenceBindingModifyDto iovFenceBindingModifyDto) throws Exception {
        if (null == iovFenceBindingModifyDto) {
            logger.error("[modifyBindingFence]调用车联网，解绑围栏，入参为空");
            throw new BizException("解绑围栏失败");
        }

        Map<String, Object> paramMap = MapObjectConvertUtil.objectToMap(iovFenceBindingModifyDto);
        if (null == paramMap || paramMap.size() < 1) {
            logger.error("[modifyBindingFence]调用车联网，解绑围栏，入参转map失败");
            throw new BizException("解绑围栏失败");
        }

        IovResponseDto iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_BINDING_DELETE, paramMap);
        logger.info("[modifyBindingFence]解绑围栏调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
        if (!iovResponse.getFlag()) {
            throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
        }

        return true;
    }

    /**
     * 判断车是否在围栏内
     *
     * @param fenceId 围栏id
     * @param vin     车架号
     * @return
     */
    @Override
    public Boolean getInfence(Integer fenceId, String vin) {
        if (null == fenceId) {
            throw new BizException("围栏id不能为空");
        }
        if (StringUtils.isBlank(vin)) {
            throw new BizException("车架号不能为空");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("fenceId", fenceId);
        map.put("vin", vin);

        try {
            IovResponseDto iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_IS_INSIDE, map);
            logger.info("[getInfence]判断车是否在围栏内调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
            if (null == iovResponse) {
                throw new BizException("判断车是否在围栏内 车联网服务异常");
            }
            if (!iovResponse.getFlag()) {
                throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
            }
            String data = iovResponse.getData();
            return Boolean.parseBoolean(data);
        } catch (IOException e) {
            logger.error("[getInfence]调用车联网服务异常", e);
            throw new BizException("判断车是否在围栏内 车联网服务异常");
        }
    }

    /**
     * 解除该车辆绑定的所有围栏
     *
     * @param vin
     * @return
     */
    @Override
    public Boolean deleteAllFence(String vin) {
        if (StringUtils.isBlank(vin)) {
            throw new BizException("车架号不能为空");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        List<String> listVin = new ArrayList<>();
        listVin.add(vin);
        map.put("listVin", listVin);
        map.put("alarmType", IovFenceAlarmTypeEnum.OUT.getValue());
        try {
            IovResponseDto iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_BINDING_DELETE_ALL, map);
            logger.info("[deleteAllFence]解除该车辆绑定的所有围栏调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
            if (null == iovResponse) {
                throw new BizException("解除所有已绑围栏 车联网服务异常");
            }
            if (!iovResponse.getFlag()) {
                throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
            }
            return true;
        } catch (IOException e) {
            logger.error("[deleteAllFence]调用车联网服务异常", e);
            throw new BizException("解除所有已绑围栏 车联网服务异常");
        }
    }

    /**
     * 围栏列表
     *
     * @param fenceIdList
     * @return
     * @throws Exception
     */
    @Override
    public List<IovFenceDto> getFenceList(List<Integer> fenceIdList) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fenceIdList", fenceIdList);
        IovResponseDto iovResponse = null;
        try {
            iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_LIST, paramMap);
            logger.info("[getFenceList]查询围栏信息，调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
        } catch (IOException e) {
            logger.error("[getFenceList]调用车联网服务异常", e);
            throw new BizException("查询围栏信息 车联网服务异常");
        }

        if (null == iovResponse) {
            throw new BizException("查询围栏信息 车联网服务异常");
        }
        if (!iovResponse.getFlag()) {
            throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
        }

        return JSONObject.parseArray(iovResponse.getData(), IovFenceDto.class);
    }

    /**
     * 查询围栏是否绑定车
     *
     * @param fenceId
     * @return
     */
    @Override
    public Boolean getBindingVehicleByFenceId(Integer fenceId) {
        if (null == fenceId) {
            throw new BizException("围栏id不能为空");
        }

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fenceId", fenceId);
        IovResponseDto iovResponse = null;
        try {
            iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_IS_BINDING_VEHICLE, paramMap);
            logger.info("[getBindingVehicleByFenceId]查询围栏是否绑定车辆，调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
        } catch (IOException e) {
            logger.error("[getBindingVehicleByFenceId]调用车联网服务异常", e);
            throw new BizException("查询围栏是否绑定车辆 车联网服务异常");
        }

        if (null == iovResponse) {
            throw new BizException("查询围栏是否绑定车辆 车联网服务异常");
        }
        if (!iovResponse.getFlag()) {
            throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
        }
        String data = iovResponse.getData();
        return Boolean.parseBoolean(data);
    }

    /**
     * 根据围栏id获取信息
     *
     * @param fenceId
     * @return
     */
    @Override
    public IovFenceDto getFenceById(Integer fenceId) {
        if (null == fenceId) {
            return null;
        }

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fenceId", fenceId);
        IovResponseDto iovResponse = null;
        try {
            iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_BY_ID, paramMap);
            logger.info("[getFenceById]根据围栏ID查询围栏信息，调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
        } catch (IOException e) {
            logger.error("[getFenceById]调用车联网服务异常", e);
            throw new BizException("根据围栏ID查询围栏信息 车联网服务异常");
        }

        if (null == iovResponse) {
            throw new BizException("根据围栏ID查询围栏信息 车联网服务异常");
        }
        if (!iovResponse.getFlag()) {
            throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
        }
        return JSONObject.parseObject(iovResponse.getData(), IovFenceDto.class);
    }

    /**
     * 根据vin获取车辆所在的围栏
     *
     * @param vinList
     * @return
     */
    @Override
    public Map<String, List<IovFenceDto>> getFenceByVins(List<String> vinList) {
        Map<String, List<IovFenceDto>> result = null;
        try {
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("vinList", vinList);
            // 调用车联网获取围栏信息
            IovResponseDto iovResult = IovUtils.doPost(IovPropertyUtils.FENCE_BY_VEHICLE, paramMap);
            if (!iovResult.getFlag() || iovResult.getCode() != ResponseCodeEnum.SUCCESS.getCode()) {
                logger.error("[getFenceByVins]批量获取车辆当前所在的围栏失败：{}", JSONObject.toJSONString(iovResult));
                throw new BizException(iovResult.getCode(), iovResult.getMessage());
            }

            if (StringUtil.isEmpty(iovResult.getData())) {
                logger.error("[getFenceByVins]批量获取车辆当前行所在的围栏失败：{}", JSONObject.toJSONString(iovResult));
                return result;
            }

            result = JSON.parseObject(iovResult.getData(), new TypeReference<Map<String, List<IovFenceDto>>>() {
            });

        } catch (BizException e) {
            throw new BizException(e.getExceptionCode(), e.getMessage());
        } catch (Exception e) {
            logger.error("[getFenceByVins]批量获取车辆当前所在的围栏异常：", e);
        }
        return result;
    }

    /**
     * 根据围栏名称模糊搜索围栏信息
     *
     * @param fenceName
     * @return
     */
    @Override
    public List<IovFenceDto> getVagueFenceByName(String fenceName) {
        List<IovFenceDto> result = null;
        try {
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("fenceName", fenceName);
            // 调用车联网获取围栏信息
            IovResponseDto iovResult = IovUtils.doPost(IovPropertyUtils.FENCE_VAGUE_BY_VEHICLE, paramMap);
            if (!iovResult.getFlag() || iovResult.getCode() != ResponseCodeEnum.SUCCESS.getCode()) {
                logger.error("[getVagueFenceByName]根据围栏名称模糊搜索围栏信息失败：{}", JSONObject.toJSONString(iovResult));
                throw new BizException(iovResult.getCode(), iovResult.getMessage());
            }

            if (StringUtil.isEmpty(iovResult.getData())) {
                logger.error("[getVagueFenceByName]根据围栏名称模糊搜索围栏信息失败：{}", JSONObject.toJSONString(iovResult));
                return result;
            }

            result = JSON.parseObject(iovResult.getData(), new TypeReference<List<IovFenceDto>>() {
            });

        } catch (BizException e) {
            throw new BizException(e.getExceptionCode(), e.getMessage());
        } catch (Exception e) {
            logger.error("[getVagueFenceByName]根据围栏名称模糊搜索围栏信息失败异常：", e);
        }
        return result;
    }

    /**
     * 车辆所在围栏
     *
     * @param fenceIdList
     * @param vin
     * @return
     */
    @Override
    public Integer getInFenceId(List<Integer> fenceIdList, String vin) {
        if (null == fenceIdList || fenceIdList.size() < 1) {
            throw new BizException("围栏不存在");
        }

        if (StringUtils.isBlank(vin)) {
            throw new BizException("车架号不能为空");
        }

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fenceIds", fenceIdList);
        paramMap.put("vin", vin);
        IovResponseDto iovResponse = null;
        try {
            iovResponse = iovUtils.doPost(IovPropertyUtils.FENCE_IS_INSIDES, paramMap);
            logger.info("[getInFenceId]查询车辆所在围栏，调用车联网返回数据：" + JSONObject.toJSONString(iovResponse));
        } catch (IOException e) {
            logger.error("[getInFenceId]查询调用车联网服务异常", e);
            throw new BizException("查询车辆所在围栏 车联网服务异常");
        }

        if (null == iovResponse) {
            throw new BizException("查询车辆所在围栏 车联网服务异常");
        }
        if (!iovResponse.getFlag()) {
            throw new BizException(iovResponse.getCode(), iovResponse.getMessage());
        }
        String data = iovResponse.getData();
        return Integer.valueOf(data);
    }


}
